﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BC.CommonConfig;
using System.IO;
using OPCAutomation;
using System.Threading;
using System.Reflection;

namespace BC.OPC
{
    /// <summary>
    /// OPC客户端处理类
    /// </summary>
    public class OpcClient
    {
        #region 事件和委托

        public delegate void DataChangeHandler(string TagName, object TagValue);

        public delegate void AsyncWriteCompleteHandler(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors);

        public delegate void AsyncReadCompleteHandler(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array Errors);

        public delegate void AsyncCancelCompleteHandler(int CancelID);

        /// <summary>
        /// 数据订阅 处理事件
        /// </summary>
        public event DataChangeHandler DataChangeEvent;
        /// <summary>
        /// 异步写完成 处理事件
        /// </summary>
        public event AsyncWriteCompleteHandler AsyncWriteCompleteEvent;
        /// <summary>
        /// 异步读完成 处理事件
        /// </summary>
        public event AsyncReadCompleteHandler AsyncReadCompleteEvent;
        /// <summary>
        /// 异步取消完成 处理事件
        /// </summary>
        public event AsyncCancelCompleteHandler AsyncCancelCompleteEvent;

        #endregion

        /// <summary>
        /// 订阅式OPC客户端 构造函数
        /// </summary>
        /// <param name="appTagList">应用变量</param>
        public OpcClient(List<string> appTagNameList)
        {
            SetOpcClientConfig();

            this.listAppTagName = appTagNameList;

            if (this._conf != null && this.listAppTagName != null)
            {
                KepServer = new OPCServer();
            }
        }

        private void SetOpcClientConfig()
        {
            #region 初始化配置实体
            //OPC客户端配置文件路径
            string ss = System.AppDomain.CurrentDomain.BaseDirectory;
            string opcClientConfigPath = ss + "OpcClientConfig.xml";
            if (File.Exists(opcClientConfigPath))
            {
                using (StreamReader sr = new StreamReader(opcClientConfigPath))
                {
                    string strxml = sr.ReadToEnd();
                    sr.Close();
                    this._conf = (OpcClientConfig)XmlUtil.Deserialize(typeof(OpcClientConfig), strxml);
                }
            }
            #endregion
        }

        ~OpcClient()
        {
            if (KepServer != null)
            {
                KepServer.Disconnect();
                KepServer = null;
            }
        }


        #region 属性
        /// <summary>
        /// 配置实体
        /// </summary>
        private OpcClientConfig _conf = null;
        /// <summary>
        /// 配置实体
        /// </summary>
        public OpcClientConfig Conf
        {
            get { return _conf; }
        }

        /// <summary>
        /// OPC变量
        /// </summary>
        private List<OpcTag> listOpcTag = null;
        /// <summary>
        /// OPC变量
        /// </summary>
        public List<OpcTag> ListOpcTag
        {
            get { return listOpcTag; }
        }

        /// <summary>
        /// 应用变量名
        /// </summary>
        private List<string> listAppTagName = null;
        /// <summary>
        /// 应用变量名
        /// </summary>
        public List<string> ListAppTagName
        {
            get { return listAppTagName; }
        }

        #endregion

        #region OPC字段变量

        /// <summary>
        /// OPCServer Object
        /// </summary>
        public OPCServer KepServer;

        /// <summary>
        /// OPCGroups Object
        /// </summary>
        OPCGroups KepGroups;

        /// <summary>
        /// OPCGroup Object
        /// </summary>
        OPCGroup KepGroup;

        OPCItems kepItems;
        /// <summary>
        /// OPCItems Object
        /// </summary>
        public OPCItems KepItems
        {
            get { return kepItems; }
        }

        /// <summary>
        /// OPCItem Object
        /// </summary>
        OPCItem KepItem;

        /// <summary>
        /// 主机IP
        /// </summary>
        string strHostIP = string.Empty;

        /// <summary>
        /// 主机名称
        /// </summary>
        string strHostName = string.Empty;

        /// <summary>
        /// 连接状态
        /// </summary>
        bool opc_connected = false;

        /// <summary>
        /// 客户端句柄
        /// </summary>
        int itmHandleClient = 0;

        /// <summary>
        /// 服务端句柄
        /// </summary>
        int itmHandleServer = 0;

        #endregion

        #region OPC初始化方法


        /// <summary>
        /// 创建组
        /// </summary>
        private bool CreateGroup()
        {
            try
            {
                KepGroups = KepServer.OPCGroups;
                KepGroup = KepGroups.Add("OPCDOTNETGROUP");
                SetGroupProperty();
                KepGroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
                KepGroup.AsyncWriteComplete += new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
                KepGroup.AsyncReadComplete += new DIOPCGroupEvent_AsyncReadCompleteEventHandler(KepGroup_AsyncReadComplete);
                KepGroup.AsyncCancelComplete += new DIOPCGroupEvent_AsyncCancelCompleteEventHandler(KepGroup_AsyncCancelComplete);
                kepItems = KepGroup.OPCItems;
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile(err.Message, this._conf.LogFileName);
                return false;
            }
            return true;
        }


        /// <summary>
        /// 设置组属性
        /// </summary>
        private void SetGroupProperty()
        {
            KepServer.OPCGroups.DefaultGroupIsActive = this._conf.GroupIsActive; ;
            KepServer.OPCGroups.DefaultGroupDeadband = this._conf.GroupDeadband;
            KepGroup.UpdateRate = this._conf.UpdateRate;
            KepGroup.IsActive = this._conf.IsActive;
            KepGroup.IsSubscribed = this._conf.IsSubscribed;
        }

        /// <summary>
        /// 列出OPC服务器中所有节点
        /// </summary>
        /// <param name="oPCBrowser"></param>
        private void ShowBrowser(OPCBrowser oPCBrowser)
        {
            //展开分支
            oPCBrowser.ShowBranches();
            //展开叶子
            oPCBrowser.ShowLeafs(true);
            //初始化OPC变量
            listOpcTag = new List<OpcTag>();
            int xHandle = 100000;
            foreach (object turn in oPCBrowser)
            {
                string tagName = turn.ToString();
                string[] str = tagName.Split('.');
                if (str[0].ToLower() != this._conf.OpcTagFilter.ToLower()
                    && str[0] != @"#MonitorACLFile"
                    && str[0] != @"@Clients")
                {
                    ++xHandle;
                    listOpcTag.Add(new OpcTag { TagName = turn.ToString(), ClientHandle = xHandle });
                }
            }
        }

        /// <summary>
        /// 获取服务器信息，写入日志
        /// </summary>
        private void GetServerInfo()
        {
            //LogUtil.WriteLogFile("开始时间:" + KepServer.StartTime.ToString(), this._conf.LogFileName);
            //LogUtil.WriteLogFile("版本:"
            //    + KepServer.MajorVersion.ToString()
            //    + "." + KepServer.MinorVersion.ToString()
            //    + "." + KepServer.BuildNumber.ToString()
            //    , this._conf.LogFileName);

        }

        /// <summary>
        /// 连接OPC服务器
        /// </summary>
        /// <param name="remoteServerIP">OPCServerIP</param>
        /// <param name="remoteServerName">OPCServer名称</param>
        private bool ConnectRemoteServer(string remoteServerIP, string remoteServerName)
        {
            try
            {
                KepServer.Connect(remoteServerName, remoteServerIP);

                if (KepServer.ServerState == (int)OPCServerState.OPCRunning)
                {
                    this.opc_connected = true;
                }
                else
                {
                    this.opc_connected = false;
                }
            }
            catch (Exception err)
            {
                this.opc_connected = false;
                LogUtil.WriteLogFile(err.Message, this._conf.LogFileName);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <returns></returns>
        public bool OpcClientServerInitialize()
        {
            try
            {
                if (!ConnectRemoteServer(this._conf.IPAddress, this._conf.ServiceName))
                {
                    return false;
                }

                opc_connected = true;

                GetServerInfo();

                ShowBrowser(KepServer.CreateBrowser());

                if (!CreateGroup())
                {
                    return false;
                }
                return true;
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile(err.Message, this._conf.LogFileName);
                return false;
            }
        }


        #endregion


        #region 数据订阅


        /// <summary>
        /// 每当项数据有变化时执行的事件（数据订阅事件）
        /// </summary>
        /// <param name="TransactionID">事务ID</param>
        /// <param name="NumItems">项个数</param>
        /// <param name="ClientHandles">项客户端句柄</param>
        /// <param name="ItemValues">TAG值</param>
        /// <param name="Qualities">品质</param>
        /// <param name="TimeStamps">时间戳</param>
        private void KepGroup_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            #region 数据订阅
            //OPC数组是从1开始的。
            for (int i = 1; i <= NumItems; i++)
            {
                int clientHandle = Convert.ToInt32(ClientHandles.GetValue(i));
                string tagName = FindClientHandle(clientHandle);

                OpcTag opcTag = new OpcTag();
                opcTag.TagName = tagName;
                opcTag.ClientHandle = clientHandle;
                opcTag.TagValue = ItemValues.GetValue(i);
                opcTag.Quality = Qualities.GetValue(i);
                opcTag.TimeStamp = TimeStamps.GetValue(i);

                ThreadPool.QueueUserWorkItem(new WaitCallback(HandleTagValue), opcTag);
            }
            #endregion
        }


        /// <summary>
        /// 数据订阅式_数据处理
        /// </summary>
        /// <param name="opcTag"></param>
        private void HandleTagValue(object opcTag)
        {
            OpcTag tag = opcTag as OpcTag;
            //事件带来的好处呀，杠杠的
            if (DataChangeEvent != null)
            {
                DataChangeEvent(tag.TagName, tag.TagValue);
            }
        }


        #endregion

        #region OPC变量集合_处理函数

        /// <summary>
        /// 查询_变量名 By clientHandle
        /// </summary>
        /// <param name="clientHandle">变量客户端句柄</param>
        /// <returns>变量名</returns>
        private string FindClientHandle(int clientHandle)
        {
            OpcTag opcClientItem = listOpcTag.Where(o => o.ClientHandle == clientHandle).First();
            return opcClientItem.TagName;
        }

        /// <summary>
        /// 查询_客户端句柄 By tagName
        /// </summary>
        /// <param name="clientHandle">变量名</param>
        /// <returns>变量客户端句柄</returns>
        private int FindTagName(string tagName)
        {
            OpcTag opcClientItem = listOpcTag.Where(o => o.TagName == tagName).First();
            return opcClientItem.ClientHandle;
        }

        #endregion

        #region 异步写入和读取
        //批量写入和批量读取暂时不支持

        /// <summary>
        /// 异步写入
        /// </summary>
        /// <param name="TransactionID">事务id（写入和写入完成的事务id必须一致）</param>
        /// <param name="tagName"></param>
        /// <param name="tagValue"></param>
        /// <param name="result"></param>
        public void OpcAsyncWrite(int TransactionID, string tagName, object tagValue, out bool result, out int CancelID)
        {
            result = false;
            CancelID = 0;
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[2] { 0, listOpcTag.Where(o => o.TagName == tagName).First().ServerHandle };
                Array serverHandles = (Array)temp;
                object[] valueTemp = new object[2] { "", tagValue };
                Array values = (Array)valueTemp;
                Array Errors;
                KepGroup.AsyncWrite(1, ref serverHandles, ref values, out Errors, TransactionID, out CancelID);

                result = (Errors.GetValue(1).ToString() == "0") ? true : false;

                GC.Collect();
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC异步写入错误******：" + err.Message, this._conf.LogFileName);
            }
        }

        #region 异步写入多个变量

        public void OpcAsyncWriteByList(int TransactionID, List<string> tagNames, List<object> tagValues, out List<bool> results, out int CancelID)
        {
            results = new List<bool>() { };
            CancelID = 0;
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[tagNames.Count + 1];
                object[] valueTemp = new object[tagNames.Count + 1];
                temp[0] = 0;
                valueTemp[0] = "";
                for (int i = 0; i < tagNames.Count; i++)
                {
                    temp[i + 1] = listOpcTag.Where(o => o.TagName == tagNames[i]).First().ServerHandle;
                    //valueTemp[i + 1] = listOpcTag.Where(o => o.TagName == tagValues[i]).First().TagValue;
                    valueTemp[i + 1] = tagValues[i];
                }
                Array serverHandles = (Array)temp;
                Array values = (Array)valueTemp;
                Array Errors;

                KepGroup.AsyncWrite(tagNames.Count, ref serverHandles, ref values, out Errors, TransactionID, out CancelID);

                for (int i = 0; i < tagNames.Count; i++)
                {
                    results.Add((Errors.GetValue(i + 1).ToString() == "0") ? true : false);
                }

                GC.Collect();
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC异步写入错误******：" + err.Message, this._conf.LogFileName);
            }
        }

        #endregion

        void KepGroup_AsyncWriteComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
        {
            if (AsyncWriteCompleteEvent != null)
            {
                AsyncWriteCompleteEvent(TransactionID, NumItems, ref  ClientHandles, ref  Errors);
            }
        }


        /// <summary>
        /// 异步读取
        /// </summary>
        /// <param name="TransactionID">事务id（读取和读取完成的事务id必须一致）</param>
        /// <param name="tagName"></param>
        /// <param name="result"></param>
        public void OpcAsyncRead(int TransactionID, string tagName, out bool result, out int CancelID)
        {
            result = false;
            CancelID = 0;
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[2] { 0, listOpcTag.Where(o => o.TagName == tagName).First().ServerHandle };
                Array serverHandles = (Array)temp;
                Array Errors;
                KepGroup.AsyncRead(1, ref serverHandles, out Errors, TransactionID, out CancelID);

                result = (Errors.GetValue(1).ToString() == "0") ? true : false;

                GC.Collect();
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC异步读取错误******：" + err.Message, this._conf.LogFileName);
            }
        }

        #region 异步读取多个变量
        /// <summary>
        /// 异步读取多个变量
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="tagNames"></param>
        /// <param name="results"></param>
        /// <param name="CancelID"></param>
        public void OpcAsyncReadByList(int TransactionID, List<string> tagNames, out List<bool> results, out int CancelID)
        {
            results = new List<bool>() { };
            CancelID = 0;
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[tagNames.Count + 1];
                temp[0] = 0;
                for (int i = 0; i < tagNames.Count; i++)
                {
                    temp[i + 1] = listOpcTag.Where(o => o.TagName == tagNames[i]).First().ServerHandle;
                }

                Array serverHandles = (Array)temp;
                Array Errors;
                KepGroup.AsyncRead(tagNames.Count, ref serverHandles, out Errors, TransactionID, out CancelID);

                for (int i = 0; i < tagNames.Count; i++)
                {
                    results.Add((Errors.GetValue(i + 1).ToString() == "0") ? true : false);
                }

                GC.Collect();
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC异步读取错误******：" + err.Message, this._conf.LogFileName);
            }
        }

        #endregion

        void KepGroup_AsyncReadComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array Errors)
        {
            if (AsyncReadCompleteEvent != null)
            {
                AsyncReadCompleteEvent(TransactionID, NumItems, ref  ClientHandles, ref  ItemValues, ref  Qualities, ref  TimeStamps, ref  Errors);
            }
        }

        #endregion

        #region 同步写入和读取
        //批量写入和批量读取暂时不支持

        /// <summary>
        /// 同步写入
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="tagValue">变量值（object类型）</param>
        /// <param name="result"></param>
        public void OpcSyncWrite(string tagName, object tagValue, out bool result)
        {
            result = false;
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[2] { 0, listOpcTag.Where(o => o.TagName == tagName).First().ServerHandle };
                Array serverHandles = (Array)temp;
                object[] valueTemp = new object[2] { "", tagValue };
                Array values = (Array)valueTemp;
                Array Errors;
                KepGroup.SyncWrite(1, ref serverHandles, ref values, out Errors);
                //KepGroup.SyncWrite(1, ref serverHandles, ref values, out Errors);//菲尼克斯的破opc服务，妈的

                result = (Errors.GetValue(1).ToString() == "0") ? true : false;
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC同步写入错误******：" + err.Message, this._conf.LogFileName);
            }
            finally
            {
                GC.Collect();
            }

        }

        /// <summary>      
        /// 同步读取
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="tagValue">变量值（object类型）</param>
        /// <param name="result"></param>
        public void OpcSyncRead(string tagName, out object tagValue, out bool result)
        {

            result = false;
            tagValue = null;
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[2] { 0, listOpcTag.Where(o => o.TagName == tagName).First().ServerHandle };
                Array serverHandles = (Array)temp;
                Array values;
                Array Errors;
                object qualities;
                object timeStamps;
                KepGroup.SyncRead(1, 1, ref serverHandles, out values, out Errors, out qualities, out timeStamps);

                result = (Errors.GetValue(1).ToString() == "0") ? true : false;
                tagValue = values.GetValue(1);

                //GC.Collect();
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC同步读取错误******：" + err.Message, this._conf.LogFileName);
            }
            finally
            {
                GC.Collect();
            }
        }

        #region 同步写入读取多个变量

        /// <summary>
        /// 同步写入多个变量
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="tagValue">变量值（object类型）</param>
        /// <param name="results"></param>
        public void OpcSyncWriteByList(List<string> tagNames, List<object> tagValues, out  List<bool> results)
        {
            results = new List<bool>();
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[tagNames.Count + 1];
                object[] valueTemp = new object[tagNames.Count + 1];
                temp[0] = 0;
                valueTemp[0] = "";
                for (int i = 0; i < tagNames.Count; i++)
                {
                    temp[i + 1] = listOpcTag.Where(o => o.TagName == tagNames[i]).First().ServerHandle;
                    valueTemp[i + 1] = tagValues[i];
                }
                Array serverHandles = (Array)temp;
                Array values = (Array)valueTemp;
                Array Errors;

                KepGroup.SyncWrite(tagNames.Count, ref serverHandles, ref values, out Errors);
                //KepGroup.SyncWrite(1, ref serverHandles, ref values, out Errors);//菲尼克斯的破opc服务，妈的

                for (int i = 0; i < tagNames.Count; i++)
                {
                    results.Add((Errors.GetValue(i + 1).ToString() == "0") ? true : false);
                }

                //GC.Collect();
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC同步写入错误******：" + err.Message, this._conf.LogFileName);
            }
            finally
            {
                GC.Collect();
            }
        }

        /// <summary>      
        /// 同步读取多个变量
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="tagValue">变量值（object类型）</param>
        /// <param name="results"></param>
        public void OpcSyncReadByList(List<string> tagNames, out List<object> tagValues, out List<bool> results, out object qualities, out object timeStamps)
        {

            results = new List<bool>();
            tagValues = new List<object>();
            qualities = null;
            timeStamps = null;
            try
            {
                //注意array在函数内部做参数时，数据下标是从1开始的所以要考虑将第0位空出来，n个Item，就要定义n+1列数组，添加一个0，但在函数使用时，又是从左开始读取的。(针对opc)
                //否则会报错
                int[] temp = new int[tagNames.Count + 1];
                temp[0] = 0;
                for (int i = 0; i < tagNames.Count; i++)
                {
                    temp[i + 1] = listOpcTag.Where(o => o.TagName == tagNames[i]).First().ServerHandle;
                }
                Array serverHandles = (Array)temp;
                Array values;
                Array Errors;
                //object qualities;
                //object timeStamps;
                KepGroup.SyncRead(1, tagNames.Count, ref serverHandles, out values, out Errors, out qualities, out timeStamps);

                for (int i = 0; i < tagNames.Count; i++)
                {
                    results.Add((Errors.GetValue(i + 1).ToString() == "0") ? true : false);
                    tagValues.Add(values.GetValue(i + 1));
                }


                //GC.Collect();
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC同步读取错误******：" + err.Message, this._conf.LogFileName);
            }
            finally
            {
                GC.Collect();
            }
        }

        #endregion

        #endregion

        #region 异步取消时执行的事件

        public void OpcAsyncCancel(int CancelID)
        {
            try
            {
                KepGroup.AsyncCancel(CancelID);
            }
            catch (Exception err)
            {
                LogUtil.WriteLogFile("******OPC异步取消错误******：" + err.Message, this._conf.LogFileName);
            }
        }

        void KepGroup_AsyncCancelComplete(int CancelID)
        {
            if (AsyncCancelCompleteEvent != null)
            {
                AsyncCancelCompleteEvent(CancelID);
            }
        }

        #endregion

        /// <summary>
        /// 开始
        /// </summary>
        public void Start()
        {
            #region 句柄对应
            List<OpcTag> temp = new List<OpcTag>();
            int i = 0;
            foreach (OpcTag item in listOpcTag)
            {
                if (listAppTagName.Where(o => o == item.TagName).Count() <= 0)
                {
                    //if (item.TagName.Contains(".WD") || item.TagName.Contains(".WS"))
                    //{
                    //    Console.WriteLine(item.TagName);
                    //}
                    temp.Add(item);
                    continue;
                }
                try
                {
                    i++;
                    KepItem = kepItems.AddItem(item.TagName, item.ClientHandle);
                    item.ServerHandle = KepItem.ServerHandle;
                }
                catch (Exception err)
                {
                    LogUtil.WriteLogFile(err.Message, this._conf.LogFileName);
                    continue;
                }
            }
            foreach (OpcTag item in temp)
            {
                listOpcTag.Remove(item);
            }

            #endregion
        }

        /// <summary>
        /// 结束
        /// </summary>
        public void Close()
        {
            if (!opc_connected)
            {
                return;
            }

            if (KepGroup != null)
            {
                KepGroup.DataChange -= new DIOPCGroupEvent_DataChangeEventHandler(KepGroup_DataChange);
                KepGroup.AsyncWriteComplete -= new DIOPCGroupEvent_AsyncWriteCompleteEventHandler(KepGroup_AsyncWriteComplete);
                KepGroup.AsyncReadComplete -= new DIOPCGroupEvent_AsyncReadCompleteEventHandler(KepGroup_AsyncReadComplete);
                KepGroup.AsyncCancelComplete -= new DIOPCGroupEvent_AsyncCancelCompleteEventHandler(KepGroup_AsyncCancelComplete);
            }

            if (KepServer != null)
            {
                KepServer.Disconnect();
                KepServer = null;
            }

            opc_connected = false;
            //LogUtil.WriteLogFile("关闭时间：" + DateTime.Now.ToString(), this._conf.LogFileName);
        }





    }
}
